﻿using System;
using System.Collections.Generic;
using System.Text;

namespace DataStandard.Tools
{
    public class DataValue
    {
        /// <summary>
        /// 【读数据时使用】根据描述，获取真正数值。
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        public static object GetRealDataValue(DataItemDescription description)
        {
            object result = 0;

            if (description.BitIndex != -1)
            {
                var tempresult = BitConverter.ToInt16(description.NewReceivedBytes, 0);
                result = BitConverQi.GetValueBit(tempresult, description.BitIndex);
            }
            else
            {
                switch (description.Type)
                {
                    case "INT16":
                        {

                            var data = new byte[description.NewReceivedBytes.Length];
                            description.NewReceivedBytes.CopyTo(data, 0);
                            switch (description.RegisterOrder)
                            {
                                case "12":
                                    break;
                                case "21":
                                    {
                                        data[0] = description.NewReceivedBytes[1];
                                        data[1] = description.NewReceivedBytes[0];
                                    }
                                    break;
                                default:
                                    break;
                            }

                            var tempresult = BitConverter.ToInt16(data, 0);
                            result = tempresult * description.Multiple + description.Offset;
                        }
                        break;
                    case "UINT16":
                        {
                            var data = new byte[description.NewReceivedBytes.Length];
                            description.NewReceivedBytes.CopyTo(data, 0);
                            switch (description.RegisterOrder)
                            {
                                case "12":
                                    break;
                                case "21":
                                    {
                                        data[0] = description.NewReceivedBytes[1];
                                        data[1] = description.NewReceivedBytes[0];
                                    }
                                    break;
                                default:
                                    break;
                            }

                            var tempresult = BitConverter.ToUInt16(data, 0);
                            result = tempresult * description.Multiple + description.Offset;
                        }
                        break;
                    case "INT32":
                        {
                            var data = new byte[description.NewReceivedBytes.Length];
                            description.NewReceivedBytes.CopyTo(data, 0);
                            switch (description.RegisterOrder)
                            {
                                case "1234":
                                    break;
                                case "2143":
                                    {
                                        data[0] = description.NewReceivedBytes[2];
                                        data[1] = description.NewReceivedBytes[3];
                                        data[2] = description.NewReceivedBytes[0];
                                        data[3] = description.NewReceivedBytes[1];
                                    }
                                    break;
                                case "3412":
                                    {
                                        data[0] = description.NewReceivedBytes[1];
                                        data[1] = description.NewReceivedBytes[0];
                                        data[2] = description.NewReceivedBytes[3];
                                        data[3] = description.NewReceivedBytes[2];
                                    }
                                    break;
                                case "4321":
                                    {
                                        data[0] = description.NewReceivedBytes[3];
                                        data[1] = description.NewReceivedBytes[2];
                                        data[2] = description.NewReceivedBytes[1];
                                        data[3] = description.NewReceivedBytes[0];
                                    }
                                    break;
                                default:
                                    break;
                            }

                            var tempresult = BitConverter.ToInt32(data, 0);
                            result = tempresult * description.Multiple + description.Offset;
                        }
                        break;
                    case "UINT32":
                        {
                            var data = new byte[description.NewReceivedBytes.Length];
                            description.NewReceivedBytes.CopyTo(data, 0);
                            switch (description.RegisterOrder)
                            {
                                case "1234":
                                    break;
                                case "2143":
                                    {
                                        data[0] = description.NewReceivedBytes[2];
                                        data[1] = description.NewReceivedBytes[3];
                                        data[2] = description.NewReceivedBytes[0];
                                        data[3] = description.NewReceivedBytes[1];
                                    }
                                    break;
                                case "3412":
                                    {
                                        data[0] = description.NewReceivedBytes[1];
                                        data[1] = description.NewReceivedBytes[0];
                                        data[2] = description.NewReceivedBytes[3];
                                        data[3] = description.NewReceivedBytes[2];
                                    }
                                    break;
                                case "4321":
                                    {
                                        data[0] = description.NewReceivedBytes[3];
                                        data[1] = description.NewReceivedBytes[2];
                                        data[2] = description.NewReceivedBytes[1];
                                        data[3] = description.NewReceivedBytes[0];
                                    }
                                    break;
                                default:
                                    break;
                            }

                            var tempresult = BitConverter.ToUInt32(data, 0);
                            result = tempresult * description.Multiple + description.Offset;
                        }
                        break;
                    case "BOOL":
                        {
                            var data = new byte[description.NewReceivedBytes.Length];
                            description.NewReceivedBytes.CopyTo(data, 0);

                            var tempresult = BitConverter.ToBoolean(data, 0);
                            result = tempresult;
                        }
                        break;
                    case "FLOAT":
                        {
                            var data = new byte[description.NewReceivedBytes.Length];
                            description.NewReceivedBytes.CopyTo(data, 0);
                            switch (description.RegisterOrder)
                            {
                                case "1234":
                                    break;
                                case "2143":
                                    {
                                        data[0] = description.NewReceivedBytes[2];
                                        data[1] = description.NewReceivedBytes[3];
                                        data[2] = description.NewReceivedBytes[0];
                                        data[3] = description.NewReceivedBytes[1];
                                    }
                                    break;
                                case "3412":
                                    {
                                        data[0] = description.NewReceivedBytes[1];
                                        data[1] = description.NewReceivedBytes[0];
                                        data[2] = description.NewReceivedBytes[3];
                                        data[3] = description.NewReceivedBytes[2];
                                    }
                                    break;
                                case "4321":
                                    {
                                        data[0] = description.NewReceivedBytes[3];
                                        data[1] = description.NewReceivedBytes[2];
                                        data[2] = description.NewReceivedBytes[1];
                                        data[3] = description.NewReceivedBytes[0];
                                    }
                                    break;
                                default:
                                    break;
                            }

                            var tempresult = BitConverter.ToSingle(data, 0);
                            result = tempresult * description.Multiple + description.Offset;
                        }
                        break;
                    default:
                        throw new NotSupportedException("GetRealReadValue(DataItemDescription description) 未定义数据类型");
                        break;
                }


                return result;
            }


            return result;
        }


        /// <summary>
        /// 【写入数据时使用】把数据转换成字节
        /// </summary>
        /// <param name="value"></param>
        /// <param name="description"></param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException"></exception>
        public static byte[] WriteRealValueConvertToByteS(object value, DataItemDescription description)
        {
            byte[] result = null;
            switch (description.Type)
            {
                case "INT16":
                    {
                        var tempValue = Convert.ToInt16(value);
                        var realValue = (tempValue - description.Offset) / description.Multiple;
                        result = BitConverter.GetBytes(realValue);
                    }
                    break;
                case "UINT16":
                    {
                        var tempValue = Convert.ToUInt16(value);
                        var realValue = (tempValue - description.Offset) / description.Multiple;
                        result = BitConverter.GetBytes(realValue);
                    }
                    break;
                case "INT32":
                    {
                        var tempValue = Convert.ToInt32(value);
                        var realValue = (tempValue - description.Offset) / description.Multiple;
                        result = BitConverter.GetBytes(realValue);
                    }
                    break;
                case "UINT32":
                    {
                        var tempValue = Convert.ToUInt32(value);
                        var realValue = (tempValue - description.Offset) / description.Multiple;
                        result = BitConverter.GetBytes(realValue);
                    }
                    break;
                case "BOOL":
                    {
                        var tempValue = Convert.ToBoolean(value);
                        result = BitConverter.GetBytes(tempValue);
                    }
                    break;
                case "FLOAT":
                    {
                        var tempValue = Convert.ToSingle(value);
                        var realValue = (tempValue - description.Offset) / description.Multiple;
                        result = BitConverter.GetBytes(realValue);
                    }
                    break;
                default:
                    throw new NotSupportedException("WriteValueConvertToByteS(object value, string type) 未定义数据类型");
                    break;
            }


            return result;
        }


        public static List<bool> GetBoolBits(DataItemDescription description)
        {
            var result = new List<bool>();

            switch (description.Type)
            {
                case "INT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToInt16(Value); 
                        for (int i = 0; i < 16; i++)
                        {
                            result.Add(Tools.BitConverQi.GetValueBit(tempValue, i) == 1 ? true : false);
                        }
                    }
                    break;
                case "UINT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToUInt16(Value);
                        for (int i = 0; i < 16; i++)
                        {
                            result.Add(Tools.BitConverQi.GetValueBit(tempValue, i) == 1 ? true : false);
                        }
                    }
                    break;
                default:
                    throw new NotImplementedException("GetBoolBits():INT16和UINT16才可以该转换");
                    break;
            }

            return result;
        }
        public static List<int> GetValueBits(DataItemDescription description)
        {
            var result = new List<int>();

            switch (description.Type)
            {
                case "INT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToInt16(Value);
                        for (int i = 0; i < 16; i++)
                        {
                            result.Add(Tools.BitConverQi.GetValueBit(tempValue, i));
                        }
                    }
                    break;
                case "UINT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToUInt16(Value);
                        for (int i = 0; i < 16; i++)
                        {
                            result.Add(Tools.BitConverQi.GetValueBit(tempValue, i));
                        }
                    }
                    break;
                default:
                    throw new NotImplementedException("GetValueBits():INT16和UINT16才可以该转换");
                    break;
            }


            return result;
        }

        public static bool GetBitBool_By_Index(int index, DataItemDescription description)
        {
            var result = false;

            switch (description.Type)
            {
                case "INT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToUInt16(Value);
                        result = Tools.BitConverQi.GetValueBit(tempValue, index) == 1 ? true : false;
                    }
                    break;
                case "UINT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToUInt16(Value);
                        result = Tools.BitConverQi.GetValueBit(tempValue, index) == 1 ? true : false;
                    }
                    break;
                default:
                    throw new NotImplementedException("GetBitBool_By_Index(int index):INT16和UINT16才可以该转换");
                    break;
            }


            return result;
        }

        public static int GetBitValue_By_Index(int index, DataItemDescription description)
        {
            var result = 0;

            switch (description.Type)
            {
                case "INT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToInt16(Value);
                        result = Tools.BitConverQi.GetValueBit(tempValue, index);
                    }
                    break;
                case "UINT16":
                    {
                        var Value = GetRealDataValue(description);
                        var tempValue = Convert.ToUInt16(Value);
                        result = Tools.BitConverQi.GetValueBit(tempValue, index);
                    }
                    break;
                default:
                    throw new NotImplementedException("GetBitValue_By_Index(int index):INT16和UINT16才可以该转换");
                    break;
            }


            return result;
        }
    }
}
